﻿using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;


using Idlesoft.Utils;

namespace Idlesoft.Utils
{
	public sealed class StringWriterWithEncoding : StringWriter
	{
		private readonly Encoding _Encoding;

		public StringWriterWithEncoding(Encoding encoding)
		{
			_Encoding = encoding;
		}
		public override Encoding Encoding { get { return _Encoding; } }
	}

	public static class SerializationExtensions
	{
		#region consts
		public const string XML_EXT = ".xml";
		#endregion consts

		#region props
		public static XmlSerializerNamespaces Namespaces
		{
			get
			{
				var namespaces = new XmlSerializerNamespaces();
				namespaces.Add("", "");
				return namespaces;
			}
		}
		#endregion props

		#region serialization
		public static XmlSerializer Serializer<TItem>()
		{
			return new XmlSerializer(typeof(TItem));
		}
		public static string Serialize<TItem>(this TItem item, XmlSerializerNamespaces namespaces = null)
		{
			string xml = null;

			using (var sw = new StringWriterWithEncoding(Encoding.UTF8))
			{
				Serializer<TItem>().Serialize(sw, item, namespaces == null ? Namespaces : namespaces);
				xml = sw.ToString();
			}
			return xml;
		}
		public static void Serialize<TItem>(this TItem item, string file, XmlSerializerNamespaces namespaces = null)
		{
			if (!file.IsNullOrEmpty())
			{
				if (!file.HasExt(XML_EXT))
					file += XML_EXT;
				using (var sw = new StreamWriter(file))
				{
					Serializer<TItem>().Serialize(sw, item, namespaces == null ? Namespaces : namespaces);
				}
			}
		}
		public static void Serialize<TItem>(this TItem item, XmlWriter writer, XmlSerializerNamespaces namespaces = null)
		{
			Serializer<TItem>().Serialize(writer, item, namespaces == null ? Namespaces : namespaces);
		}
		public static TItem Deserialize<TItem>(this string xmlOrFile)
		{
			TItem item = default(TItem);

			if (!xmlOrFile.IsNullOrEmpty())
			{
				if (xmlOrFile.Contains('<'))
				{
					string xml = xmlOrFile;
					using (var sr = new StringReader(xml))
					{
						item = (TItem)Serializer<TItem>().Deserialize(sr);
					}
				}
				else if (xmlOrFile.FileExists() && Path.GetExtension(xmlOrFile) == XML_EXT)
				{
					string file = Path.GetFullPath(xmlOrFile);
					using (var sr = new StreamReader(xmlOrFile))
					{
						item = (TItem)Serializer<TItem>().Deserialize(sr);
					}
				}
			}
			return item;
		}
		public static TItem Deserialize<TItem>(this XmlReader reader)
		{
			TItem item = default(TItem);

			item = (TItem)Serializer<TItem>().Deserialize(reader);

			return item;
		}
		#endregion serialization
	}
}

